﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using hegang_winform.services;
using hegang_winform.domain;
using hegang_winform.dao;
using hegang_winform.utils;
using OPCAutomation;
using Hegang.APP.Services.DbService;

namespace hegang_winform.views
{
    public partial class MainForm : Form
    {
        private KEPWareDataAdapter da=new KEPWareDataAdapter();
        private Dictionary<string, List<string>> devices;
        DbServiceInput input;
        private List<string> channel_device_list=new List<string>();
        //DateTime nowTime=DateTime.Now;
        private TimeJudgeItemList timeJudgeItemList=new TimeJudgeItemList();
        private DataSaveService dataSaveService = new DataSaveService();
        private FixedTimeTaskService fixedTimeTaskService = new FixedTimeTaskService();

        public MainForm()
        {
            InitializeComponent();
            treeView.FullRowSelect = false;
            try
            {
                this.rtb_console.AppendText("KEPWareDataAdapter对象已完成初始化。\n");
                object serverList = da.GetLocalServer();
                foreach (string str in (Array)serverList)
                    this.cb_opcList.Items.Add(str);
                this.cb_opcList.SelectedIndex = 0;
                connectOPCServer(cb_opcList.Text);
                initTreeView();
                checkAll();

                initChannel_device_list();
                initDic();
                da.CreateGroup(channel_device_list);
                for (int i = 0; i < channel_device_list.Count; i++)
                    da.MyGroups[i].DataChange += new DIOPCGroupEvent_DataChangeEventHandler(GroupDataChange);

               /*for (int i = 0; i < channel_device_list.Count; i++)
                    da.MyGroups[i].AsyncReadComplete += new DIOPCGroupEvent_AsyncReadCompleteEventHandler(GroupAsyncReadComplete);*/

                /*OPCGroup group;
                group.OPCItems.AddItem("副井.副提升电控.提人方式", 1);
                group.OPCItems.AddItem("副井.副提升电控.提物方式", 2);*/

                //group.AsyncReadComplete += GroupAsyncReadComplete;

                //da.readData(1);



                fixedTimeTaskService.executeTask();
                rtb_console.AppendText("开始存储数据。\n");
            }
            catch(Exception e)
            {
                this.rtb_console.AppendText(e.Message);
            }
        }

        /// <summary>
        /// 异步读完成
        /// 运行时，Array数组从下标1开始而非0！
        /// </summary>
        /// <param name="TransactionID"></param>
        /// <param name="NumItems"></param>
        /// <param name="ClientHandles"></param>
        /// <param name="ItemValues"></param>
        /// <param name="Qualities"></param>
        /// <param name="TimeStamps"></param>
        /// <param name="Errors"></param>
        void GroupAsyncReadComplete(int TransactionID, int NumItems, ref System.Array ClientHandles, ref System.Array ItemValues, ref System.Array Qualities, ref System.Array TimeStamps, ref System.Array Errors)
        {
            Console.WriteLine("****************GroupAsyncReadComplete*******************");

            //Console.WriteLine("Tran：{0}   ClientHandles：{1}   Error：{2}", TransactionID.ToString(), ClientHandles.GetValue(i).ToString(), Errors.GetValue(i).ToString());
            //Console.WriteLine("Vaule：{0}", Convert.ToString(ItemValues.GetValue(i)));

            #region 初始化参数
            ///////////////////////////////////////////////////////
            Array clientHandles = ClientHandles;
            Array itemValues = ItemValues;
            ///////////////////////////////////////////////////////

            /*  存储相应信息
            * time         时间戳
            * channel      通道名称
            * devicename   设备名称
            * ItemName     标记名称
            */
            //string time = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            string[] channel = new string[NumItems];
            string[] device = new string[NumItems];
            string[] itemName = new string[NumItems];
            for (int i = 1; i <= NumItems; i++)
            {
                channel[i - 1] = (da.htOpcItems[(int)clientHandles.GetValue(i) - 1] + "").Split(new char[] { '.' })[0];
                device[i - 1] = (da.htOpcItems[(int)clientHandles.GetValue(i) - 1] + "").Split(new char[] { '.' })[1];
                itemName[i - 1] = (da.htOpcItems[(int)clientHandles.GetValue(i) - 1] + "").Split(new char[] { '.' })[2];
            }
            #endregion

            for (int i = 1; i <= NumItems; i++)
            {
                string text = string.Format("{0} {1} {2} {3} {4}", channel[i - 1], device[i - 1], itemName[i - 1], itemValues.GetValue(i).ToString(), ((int)clientHandles.GetValue(i) - 1).ToString());
                Console.WriteLine(text);
            }

            
        }

        /// <summary>
        /// 每当项数据有变化时执行的事件,从1开始
        /// </summary>
        /// <param name="TransactionID">处理ID</param>
        /// <param name="NumItems">项个数</param>
        /// <param name="ClientHandles">项客户端句柄</param>
        /// <param name="ItemValues">TAG值</param>
        /// <param name="Qualities">品质</param>
        /// <param name="TimeStamps">时间戳</param>
        void GroupDataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
        {
            #region 初始化参数
            ///////////////////////////////////////////////////////
            Array clientHandles = ClientHandles;
            Array itemValues = ItemValues;
            ///////////////////////////////////////////////////////

            /*  存储相应信息
            * time         时间戳
            * channel      通道名称
            * devicename   设备名称
            * ItemName     标记名称
            */
            string time = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            string[] channel = new string[NumItems];
            string[] device = new string[NumItems];
            string[] itemName = new string[NumItems];
            for (int i = 1; i <= NumItems; i++)
            {
                channel[i - 1] = (da.htOpcItems[(int)clientHandles.GetValue(i) - 1] + "").Split(new char[] { '.' })[0];
                device[i - 1] = (da.htOpcItems[(int)clientHandles.GetValue(i) - 1] + "").Split(new char[] { '.' })[1];
                itemName[i - 1] = (da.htOpcItems[(int)clientHandles.GetValue(i) - 1] + "").Split(new char[] { '.' })[2];
            }
            #endregion

            #region 数据展示
            //ListView设置1s更新一次，如果不设置更新间隔，会出现"高度必须为非负值"错误
            /*if ((DateTime.Now - nowTime).TotalMilliseconds > 200)
            {
                for (int i = 1; i <= NumItems; i++)
                {
                    *//*if (rtb_console.Lines.Length >= 100)
                        rtb_console.Text = rtb_console.Text.Remove(rtb_console.Text.Length - 1);*//*
                    string text=string.Format("{0} {1} {2} {3} {4} {5}\n", channel[i - 1], device[i - 1], itemName[i - 1], itemValues.GetValue(i).ToString(), ((int)clientHandles.GetValue(i) - 1).ToString(),time);
                    rtb_console.AppendText(text);
                }
                nowTime = DateTime.Now;
            }*/
            #endregion

            #region 数据存储
            //重置时间判断列表每一项的标志位
            timeJudgeItemList.resetFlags();

            for (int i = 0; i < NumItems; i++)
            {
                set_data_to_dic(channel[i], device[i], itemName[i], itemValues.GetValue(i + 1).ToString());
                // 将故障信息存入数据库
                if (channel[i] == "故障" && itemValues.GetValue(i + 1).ToString() == "True")
                    Gz.save(dataSaveService.O, device[i], itemName[i]);
            }

            //重置时间判断列表每一项的时间信息
            timeJudgeItemList.resetTimeList();

            //将出故障外的PLC数据存储到数据库
            dataSaveService.savePLCData(ref input, timeJudgeItemList);
            #endregion
        }

        /// <summary>
        /// 将PLC数据设置到字典中
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="device"></param>
        /// <param name="itemName"></param>
        /// <param name="itemValue"></param>
        public void set_data_to_dic(string channel, string device, string itemName, string itemValue)
        {
            string key = channel + "." + device + "." + itemName;
            if (input.Dic.ContainsKey(key))
                input.Dic[key] = itemValue;
        }

        private void initChannel_device_list()
        {
            if(channel_device_list==null)
                channel_device_list = new List<string>();
            channel_device_list.Clear();
            foreach (TreeNode channel in treeView.Nodes)
            {
                if (channel.Checked == true)
                {
                    foreach (TreeNode device in channel.Nodes)
                    {
                        if (device.Checked == true)
                            channel_device_list.Add(channel.Text + "." + device.Text);
                    }
                }
            }
        }

        private void connectOPCServer(string opcSeverName)
        {
            try
            {
                Result result=da.ConnectRemoteServer(opcSeverName);
                this.rtb_console.AppendText(result.Msg+"\n");    
            }
            catch(Exception e)
            {
                this.rtb_console.AppendText(e.Message);
            }
        }
        private void initTreeView()
        {
            if (this.devices == null)
                this.devices = da.GetPLCDevices();
            List<TreeNode> parentNodes = new List<TreeNode>();
            foreach (string key in devices.Keys)
            {
                TreeNode parentNode = new TreeNode();
                parentNode.Text = key;
                foreach(string value in devices[key])
                {
                    TreeNode childNode = new TreeNode();
                    childNode.Text = value;
                    parentNode.Nodes.Add(childNode);
                }
                parentNodes.Add(parentNode);
            }
            foreach (TreeNode n in parentNodes)
                treeView.Nodes.Add(n);
        }

        private void treeView_AfterCheck(object sender, TreeViewEventArgs e)
        {
            TreeNode curNode = e.Node;
            int level = curNode.Level;
            if (level == 1)
            {
                TreeNode parentNode = curNode.Parent;
                if (curNode.Checked)
                    parentNode.Checked = true;
                else
                {
                    foreach(TreeNode childNode in parentNode.Nodes)
                    {
                        if (childNode.Checked)
                            return;
                    }
                    parentNode.Checked = false;
                }
            }
            else
            {
                if (e.Action != TreeViewAction.Unknown)
                {
                    curNode.Expand();
                    foreach (TreeNode childNode in curNode.Nodes)
                        childNode.Checked = curNode.Checked?true:false;
                }
            }
        }
        private void checkAll()
        {
            treeView.ExpandAll();
            foreach(TreeNode parentNode in treeView.Nodes)
            {
                parentNode.Checked = true;
                foreach (TreeNode childNode in parentNode.Nodes)
                    childNode.Checked = true;
            }
        }

        /// <summary>
        /// 初始化字典
        /// </summary>
        private void initDic()
        {
            input = new DbServiceInput();
            //初始化dic
            foreach (TreeNode channel in this.treeView.Nodes)
            {
                foreach (TreeNode device in channel.Nodes)
                {
                    List<string> itemList = CSVUtils.getTpNames(device.Text);
                    if (itemList != null)
                    {
                        foreach (string itemName in itemList)
                        {
                            string key = channel.Text + "." + device.Text + "." + itemName;
                            if (key == "主井.主提升电控.高度")
                            {
                                input.Dic.Add(key, "480.5");
                            }
                            else
                            {
                                input.Dic.Add(key, "0");
                            }
                        }
                    }
                    else
                    {
                        rtb_console.AppendText(string.Format("点表：{0}不存在！\n", device.Text));
                    }
                }
            }
            rtb_console.AppendText("PLC点表初始化完成。\n");
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            System.Environment.Exit(0);
        }
    }
}
